package spring.cloud.tasks.executor.executor.task.task_item_execute;

import com.alibaba.fastjson2.JSON;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import spring.cloud.tasks.common.YN;
import spring.cloud.tasks.common.nodepaths.RenewalNodePaths;
import spring.cloud.tasks.common.task.TaskItemExecuteRenewalInfo;
import spring.cloud.tasks.executor.executor.task.Service;
import spring.cloud.tasks.executor.executor.task.TaskExecutor;
import spring.cloud.tasks.executor.executor.task.execute_runtime_context.TaskItemExecuteRuntimeContext;

@Slf4j
@Setter
@Getter
public class TaskItemExecuteRenewalInfoService extends Service {
    public TaskItemExecuteRenewalInfoService(TaskExecutor taskExecutor) {
        super(taskExecutor);
    }

    /**
     * 需要进行续期判断，如果之前的执行器还在执行，那么等待。那么当前任务分片实例则标记为等待其他执行器完成或者下线。有可能最后任务都执行不了。
     *
     * @param taskItemExecuteRuntimeContext
     */
    public void registerTaskItemExecuteRenewalInfo(TaskItemExecuteRuntimeContext taskItemExecuteRuntimeContext) {
        try {
            String taskItemIndexRenewalNodePath = RenewalNodePaths.getTaskAndTaskInstanceAndTaskStageAndTaskStage$typeAndTaskStage$type$indexNodePath(//
                    taskItemExecuteRuntimeContext.getTaskId(),//
                    taskItemExecuteRuntimeContext.getTaskInstanceId(), //
                    taskItemExecuteRuntimeContext.getTaskStage(), //
                    taskItemExecuteRuntimeContext.getTaskStage$type(),//
                    String.valueOf(taskItemExecuteRuntimeContext.getTaskStage$type$index()));//
            TaskItemExecuteRenewalInfo taskItemExecuteRenewalInfo = RenewalNodePaths.getTaskItemExecuteRenewalInfo(taskExecutor.getCurator(), taskItemIndexRenewalNodePath);
            if (taskItemExecuteRenewalInfo == null) {
                taskItemExecuteRenewalInfo = new TaskItemExecuteRenewalInfo(
                        taskItemExecuteRuntimeContext.getTaskId(),//
                        taskItemExecuteRuntimeContext.getTaskInstanceId(),//
                        taskItemExecuteRuntimeContext.getTaskStage(),//
                        taskItemExecuteRuntimeContext.getTaskStage$type(),//
                        taskItemExecuteRuntimeContext.getTaskStage$type$index()//
                );
                taskItemExecuteRenewalInfo.setExecutorId(executorId);
                taskItemExecuteRenewalInfo.setNextFireDate(taskItemExecuteRuntimeContext.getNextFireDate());
                taskItemExecuteRenewalInfo.setTimeoutDateTime(taskItemExecuteRuntimeContext.getTimeoutDateTime());
                taskItemExecuteRenewalInfo.setLockDateTime(taskItemExecuteRuntimeContext.getLockDateTime());
                TaskItemExecuteRuntimeContext.RenewalTimeInfo renewalTimeInfo = taskItemExecuteRuntimeContext.calculateNewRenewalInfo();
                taskItemExecuteRenewalInfo.setLastCalculatedMaxAllowRunningTime(renewalTimeInfo.maxAllowRunningTime);
                taskItemExecuteRenewalInfo.setLastCalculatedMaxRenewalTime(renewalTimeInfo.maxRenewalTime);
                //
                this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                return;
            } else {
                if (!executorId.equals(taskItemExecuteRenewalInfo.getExecutorId())) {
                    if (!YN.Y.equals(taskItemExecuteRenewalInfo.getPreAssignCancel())) {
                        //获取之前的续期信息
                        Long lastCalculatedMaxRenewalTime = taskItemExecuteRenewalInfo.getLastCalculatedMaxRenewalTime();
                        if (System.currentTimeMillis() >= lastCalculatedMaxRenewalTime) {
                            TaskItemExecuteRuntimeContext.RenewalTimeInfo renewalTimeInfo = taskItemExecuteRuntimeContext.calculateNewRenewalInfo();
                            taskItemExecuteRenewalInfo.setExecutorId(executorId);
                            taskItemExecuteRenewalInfo.setLastCalculatedMaxAllowRunningTime(renewalTimeInfo.maxAllowRunningTime);
                            taskItemExecuteRenewalInfo.setLastCalculatedMaxRenewalTime(renewalTimeInfo.maxRenewalTime);
                            this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                            return;
                        } else {
                            taskItemExecuteRuntimeContext.isNeedReRenewalAtNextExecutePeriod = true;
                            taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期失败,续期信息中执行器不是当前的执行器,需要等待续期过期";
                            return;
                        }
//                        //如果是因为调度问题导致某个任务分片不再执行了，需要在续期信息中标记退出。
//                        taskItemExecuteRuntimeContext.isNeedReRenewalAtNextExecutePeriod = true;
//                        taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期失败<执行器不是当前的执行器>";
//                        return;
                    } else {
                        TaskItemExecuteRuntimeContext.RenewalTimeInfo renewalTimeInfo = taskItemExecuteRuntimeContext.calculateNewRenewalInfo();
                        taskItemExecuteRenewalInfo.setExecutorId(executorId);
                        taskItemExecuteRenewalInfo.setLastCalculatedMaxAllowRunningTime(renewalTimeInfo.maxAllowRunningTime);
                        taskItemExecuteRenewalInfo.setLastCalculatedMaxRenewalTime(renewalTimeInfo.maxRenewalTime);
                        this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                        return;

                    }
                } else {
                    TaskItemExecuteRuntimeContext.RenewalTimeInfo renewalTimeInfo = taskItemExecuteRuntimeContext.calculateNewRenewalInfo();
                    taskItemExecuteRenewalInfo.setLastCalculatedMaxAllowRunningTime(renewalTimeInfo.maxAllowRunningTime);
                    taskItemExecuteRenewalInfo.setLastCalculatedMaxRenewalTime(renewalTimeInfo.maxRenewalTime);
                    this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                    return;
                }
            }

        } catch (Exception e) {
            log.error("注册任务分片续期信息失败:" + JSON.toJSONString(taskItemExecuteRuntimeContext), e);
            taskItemExecuteRuntimeContext.isNeedReRenewalAtNextExecutePeriod = true;//续期操作出现异常
            taskItemExecuteRuntimeContext.renewalExceptionMessage = e.getMessage();
        }
    }

    /**
     * @param taskItemExecuteRuntimeContext
     * @param renewalTimeInfo
     * @return 如果返回null那么则最多可以运行到old.maxAllowRunningTime, 为true表示续期成功, 为false表示续期失败需要立即停止当前的任务分片。
     */
    public Boolean renewal(TaskItemExecuteRuntimeContext taskItemExecuteRuntimeContext, TaskItemExecuteRuntimeContext.RenewalTimeInfo renewalTimeInfo) {
        //获取ZK续期信息，的标记是不是自己taskItemInstanceId,如果是则续期
        try {
            String taskItemIndexRenewalNodePath = RenewalNodePaths.getTaskAndTaskInstanceAndTaskStageAndTaskStage$typeAndTaskStage$type$indexNodePath(taskItemExecuteRuntimeContext.getTaskId(), taskItemExecuteRuntimeContext.getTaskInstanceId(), taskItemExecuteRuntimeContext.getTaskStage(), taskItemExecuteRuntimeContext.taskStage$type, String.valueOf(taskItemExecuteRuntimeContext.taskStage$type$index));
            TaskItemExecuteRenewalInfo taskItemExecuteRenewalInfo = RenewalNodePaths.getTaskItemExecuteRenewalInfo(null, taskItemIndexRenewalNodePath);
            if (taskItemExecuteRenewalInfo == null) {
                taskItemExecuteRuntimeContext.needStop = true;
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "莫名的被删除了,那么就不用续期了";
                return false;//莫名的被删除了 那么就不用续期了。(ZK进行重新初始化才会出现这种情况)
            }
            if (!executorId.equals(taskItemExecuteRenewalInfo.getExecutorId())) {
                //如果是因为调度问题导致某个任务分片不再执行了，需要在续期信息中标记退出。
                taskItemExecuteRuntimeContext.needStop = true;
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期失败,续期信息中执行器不是当前的执行器";
                return false;
            } else {
                taskItemExecuteRenewalInfo.setLastCalculatedMaxAllowRunningTime(renewalTimeInfo.maxAllowRunningTime);
                taskItemExecuteRenewalInfo.setLastCalculatedMaxRenewalTime(renewalTimeInfo.maxRenewalTime);
                this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                return true;
            }

        } catch (Exception e) {
            /**
             * 续期过程中出现异常，那么还是可以运行到lastCalculatedMaxAllowRunningTime这个时间点。
             */
            //要是续期失败了 慢慢等下次续期机会 直到十分钟后还续期不成功那就不管了
            log.error("更新任务分片续期信息失败:" + JSON.toJSONString(taskItemExecuteRuntimeContext) + "," + JSON.toJSONString(renewalTimeInfo), e);
            //汇报异常信息，但是不能因为异常就进行停止处理，因为此刻的任务分片还正常跑的。
            taskItemExecuteRuntimeContext.renewalExceptionMessage = e.getMessage();
            return null;
        }
    }

    /**
     * 状态自动维护的时候，不用续期反向操作。因为任务分片线程会主动的续期，主动续期不成功则会续期反操作
     *
     * @param taskItemExecuteRuntimeContext
     * @return
     */
    public Boolean disrenewal(TaskItemExecuteRuntimeContext taskItemExecuteRuntimeContext) {
        //获取ZK续期信息，的标记是不是自己taskItemInstanceId,如果是则续期
        try {
            String taskItemIndexRenewalNodePath = RenewalNodePaths.getTaskAndTaskInstanceAndTaskStageAndTaskStage$typeAndTaskStage$type$indexNodePath(taskItemExecuteRuntimeContext.getTaskId(), taskItemExecuteRuntimeContext.getTaskInstanceId(), taskItemExecuteRuntimeContext.getTaskStage(), taskItemExecuteRuntimeContext.taskStage$type, String.valueOf(taskItemExecuteRuntimeContext.taskStage$type$index));
            TaskItemExecuteRenewalInfo taskItemExecuteRenewalInfo = RenewalNodePaths.getTaskItemExecuteRenewalInfo(null, taskItemIndexRenewalNodePath);
            if (taskItemExecuteRenewalInfo == null) {
                taskItemExecuteRuntimeContext.needStop = true;
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "莫名的被删除了,撒都不用做了";
                return true;
            }
            if (!executorId.equals(taskItemExecuteRenewalInfo.getExecutorId())) {
                //如果是因为调度问题导致某个任务分片不再执行了，需要在续期信息中标记退出。
                taskItemExecuteRuntimeContext.needStop = true;
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期信息中的执行器不是当前执行器,撒都不用做了";
                return false;
            } else {
                taskItemExecuteRuntimeContext.needStop = true;
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期信息反注册中";
                //
                taskItemExecuteRenewalInfo.setPreAssignCancel(YN.Y);
                this.curator.merge(taskItemIndexRenewalNodePath, JSON.toJSONString(taskItemExecuteRenewalInfo));
                taskItemExecuteRuntimeContext.renewalExceptionMessage = "续期信息反注册成功";
                return true;
            }

        } catch (Exception e) {
            /**
             * 续期过程中出现异常，那么还是可以运行到lastCalculatedMaxAllowRunningTime这个时间点。
             */
            //要是续期失败了 慢慢等下次续期机会 直到十分钟后还续期不成功那就不管了
            log.error("更新任务分片续期信息失败:" + JSON.toJSONString(taskItemExecuteRuntimeContext), e);
            //汇报异常信息，但是不能因为异常就进行停止处理，因为此刻的任务分片还正常跑的。
            taskItemExecuteRuntimeContext.renewalExceptionMessage = e.getMessage();
            return null;
        }
    }
}
